package com.home.security.browser.filter;

import com.home.common.constants.Constants;
import com.home.common.constants.shiro.ShiroConstant;
import com.home.common.utils.msg.MessageUtils;
import com.home.common.utils.string.StringUtils;
import com.home.security.browser.manager.AsyncManager;
import com.home.security.browser.manager.factory.AsyncFactory;
import com.home.security.browser.shiro.ShiroUtils;
import com.home.common.model.CurrentUser;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
import java.util.Deque;

/**
 * Description:
 * Created by 王大宸 on 2020-10-08 16:16
 * Created with IntelliJ IDEA.
 */
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter {
    private static final Logger logger = LoggerFactory.getLogger(LogoutFilter.class);

    /**
     * 退出后重定向的地址
     */
    private String loginUrl;

    private String clientId;

    private Cache<String, Deque<Serializable>> cache;

    public String getLoginUrl() {
        return loginUrl;
    }

    public void setLoginUrl(String loginUrl) {
        logger.info("正在配置退出地址:" + loginUrl);
        this.loginUrl = loginUrl;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        logger.info("当前客户端:" + clientId);
        this.clientId = clientId;
    }

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        try {
            Subject subject = getSubject(request, response);
            String redirectUrl = getRedirectUrl(request, response, subject);
            try {
                CurrentUser user = ShiroUtils.getUserInfo();
                if (StringUtils.isNotNull(user)) {
                    String loginName = user.getUsername();
                    // 记录用户退出日志
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getUsername(),
                            loginName,
                            getClientId(),
                            Constants.LOGOUT,
                            MessageUtils.message("user.logout.success")));
                    // 清理缓存
                    cache.remove(loginName);
                    ShiroUtils.removeCache(loginName, getClientId(), true);
                }
                // 退出登录
                subject.logout();
            } catch (SessionException ise) {
                logger.error("logout fail.", ise);
            }
            issueRedirect(request, response, redirectUrl);
        } catch (Exception e) {
            logger.error("Encountered session exception during logout.  This can generally safely be ignored.", e);
        }
        return false;
    }

    /**
     * 退出跳转URL
     */
    @Override
    protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) {
        String url = getLoginUrl();
        if (StringUtils.isNotEmpty(url)) {
            return url;
        }
        return super.getRedirectUrl(request, response, subject);
    }

    // 设置Cache的key的前缀
    public void setCacheManager(CacheManager cacheManager) {
        this.cache = cacheManager.getCache(ShiroConstant.CACHE_KEY);
    }
}
